#! /usr/bin/env python
#coding=utf-8

import sys
import time

# import factory modules
from melobook.factory import AocFactory

validatelist = ['int', 'double', 'string', 'datetime', 'yn']
class UocBase(object):
    """用户操作命令（UOC）分析基类"""
    uoclevel = 'normal'
    
    def __init__(self, uocname, uocparams=None, user=None, doc = None):
        self.uocname = uocname
        self.uocparams = uocparams
        # 包含认证，日志，配置信息的user对象
        self.user = user
        # Doc实例
        self.doc = doc
        
        # aoclist 为该uoc对应的 aoc 列表，分析完毕之后，将执行每一个aoc
        # 并且输出执行结果
        self.aoclist = []
        
    def excute(self):
        "执行该UOC"
        # 本方法为UOC提供给main的调用入口
        # uoc_parse分析出aoclist
        self.uoc_parse()
        if (not self.aoclist) or len(self.aoclist) == 0:
            self.user.log.writeLog('parse aoc fail.', 'error')
            return
        for aocitem in self.aoclist:
            pmod = AocFactory(aocitem[0])
            if not pmod:
                self.user.log.writeLog('import aoc module fail.', 'fatal')
                break
            taoc = pmod.Aoc(aocitem[0], aocitem[1], user=self.user, doc=self.doc)
            taoc.excute()

    def uoc_parse(self):
        "执行UOC分析"

        if self.user.level == None:
            self.user.log.writeLog('uoc level error, unauthenticate.', 'error')
            return None

        if self.user.level == 'normal' and self.uoclevel == 'admin':
            self.user.log.writeLog('uoc level error', 'error')
            return None

        if self.uocparams and len(self.uocparams) > 0:
            return self.direct_parse()
        else:
            return self.interact_parse()

    def direct_parse(self):
        "直接型命令分析"
        pass

    def interact_parse(self):
        "交互性命令分析"
        pass

    def get_input(self, info):
        "统一输入接口"
        print info + " 使用Ctrl+d跳出"
        strinput = sys.stdin.readline()
        if not strinput:
            self.user.log.writeLog('user cancel add uoc.', 'info')
            return None
        else:
            if strinput == '\n' or strinput == 'default':
                return 'default'
            return strinput.rstrip()
            
    # 以下三个方法分别返回输入时间所在的年，月，日的时间戳范围
    def caltime_by_year(self, caltime):
        year = time.localtime(caltime)[0]
        t1 = time.mktime((year, 1, 1, 0, 0, 0, 0, 0, 0))
        t2 = time.mktime((year + 1, 1, 1, 0, 0, 0, 0, 0, 0))
        return (t1, t2)
    
    def caltime_by_month(self, caltime):
        # 很酷的time模块，能自动处理12＋1月的问题^_^
        ct = time.localtime(caltime)
        t1 = time.mktime((ct[0], ct[1], 1, 0, 0, 0, 0, 0, 0))
        t2 = time.mktime((ct[0], ct[1] + 1, 1, 0, 0, 0, 0, 0, 0))
        return (t1, t2)
        
    def caltime_by_week(self, caltime):
        # 1 减去 2 day 也能处理lol
        # 注意我定义的一周是从这周一00:00:00到下周一00:00:00
        ct = time.localtime(caltime)
        t1 = time.mktime((ct[0], ct[1], ct[2] - ct[6], 0, 0, 0, 0, 0, 0))
        t2 = time.mktime((ct[0], ct[1], ct[2] - ct[6] + 7, 0, 0, 0, 0, 0, 0))
        return (t1, t2)

def field_validate(data, dtype, dlength=0):
    """UOC数据输入验证静态方法"""
    try:
        validatelist.index(dtype)
    except:
        return None
    if dtype == 'int':
        try:
            data = int(data)
        except:
            return None
        return data
    elif dtype == 'double':
        try:
            data = float(data)
        except:
            return None
        return data
    elif dtype == 'string':
        try:
            if type(data) != type(' '):
                return None
            if len(data) > dlength:
                return None
        except:
            return None
        return data
    elif dtype == 'datetime':
        # datetime 格式为 YYYYMMDDHHMMSS
        # 或者 YYYYMMDD
        # 或者 MMDD
        # 或者 DD
        # 或者 D
        if type(data) != type(' '):
            return None
        if len(data) != 14 and len(data) != 8 and len(data) != 4 and len(data) != 2 and len(data) != 1:
            return None
        t = None
        # 估计此处会出现隐患
        # gmtime 和 localtime
        gt = time.gmtime()
        try:
            if len(data) == 14:
                t = time.mktime((int(data[:4]), int(data[4:6]), int(data[6:8]), 
                                 int(data[8:10]), int(data[10:12]), int(data[12:14]),
                                 0, 0, 0))
            elif len(data) == 8:
                t = time.mktime((int(data[:4]), int(data[4:6]), int(data[6:8]), 
                                 0, 0, 0, 0, 0, 0))
            elif len(data) == 4:
                t = time.mktime((gt[0], int(data[:2]), int(data[2:4]), 
                                 0, 0, 0, 0, 0, 0))
            elif len(data) == 2 or len(data) == 1:
                t = time.mktime((gt[0], gt[1], int(data), 
                                 0, 0, 0, 0, 0, 0))
        except:
            return None
        return t
    elif dtype == 'yn':
        try:
            if type(data) != type(' '):
                return None
            if data == 'y' or data == 'Y':
                data = 'y'
            elif data == 'N' or data == 'n':
                data = 'n'
            else:
                return None
        except:
            return None
        return data
    return None

if __name__ == '__main__':
    print dir(AocFactory)
    
    # uoc = UocBase('', '', '')
    print field_validate('10', 'int')
    print field_validate('10.1', 'int')
    print field_validate('10.1', 'double')
    print field_validate('5', 'double')
    print field_validate('5e', 'double')
    print field_validate('19860101', 'datetime')
    print field_validate('20050203125635', 'datetime')
    print field_validate('200502031256x5', 'datetime')
    print field_validate('2005020312563', 'datetime')
